HAProxy 反向代理 SSL

生成haproxy 终结证书

openssl genrsa -out /etc/haproxy/server.key 2048
openssl req -new -key /etc/haproxy/server.key -out /etc/haproxy/server.csr
openssl x509 -req -days 3655 -in /etc/haproxy/server.csr -signkey /etc/haproxy/server.key -out /etc/haproxy/server.crt

## 以上三步合为一步操作
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/haproxy/server.key -out /etc/haproxy/server.crt

## 除了cn需要输入网站名,其它可以随意输入
## openssl:    这是OpenSSL提供的基本命令行工具,用于创建和管理证书,密钥,签名请求等。
## req:        这指定了X.509证书签名请求(CSR)管理的子命令。X.509是SSL为其密钥和证书管理所遵循的公钥基础结构标准。由于我们想要创建一个新的X.509证书,这就是我们想要的。
## -x509:      此选项指定我们要创建自签名证书文件,而不是生成证书请求。
## -nodes:     此选项告诉OpenSSL我们不希望使用密码来保护我们的密钥文件。拥有受密码保护的密钥文件会妨碍Apache自动启动,因为每次服务重新启动时都必须输入密码。
## -days 365:  这指定我们创建的证书有效期为一年。
## -newkey rsa:2048:此选项将同时创建证书请求和新私钥。这是必要的,因为我们没有提前创建私钥。该rsa:2048告诉OpenSSL生成RSA密钥是2048位。
## -keyout:    此参数为正在创建的私钥文件命名输出文件。
## -out:       此选项为我们生成的证书命名输出文件。


## pem文件本质上只是将证书、密钥及证书认证中心证书(可有可无)拼接成一个文件

cat /etc/haproxy/server.crt /etc/haproxy/server.key | tee /etc/haproxy/server.pem

Haproxy日志记录

在配置前,我们先来了解一下日志的level:local0~local7 16~23保留为本地使用:

    emerg 0 系统不可用;
    alert 1 必须马上采取行动的事件;
    crit 2 关键的事件;
    err 3 错误事件;
    warning 4 警告事件;
    notice 5 普通但重要的事件;
    info 6 有用的信息;
    debug 7 调试信息。

默认 haproxy 是不记录日志的,为了记录日志还需要配置 syslog 模块,在 linux 下是 rsyslogd 服务。

如果要发送日志到远程主机,还需修改远程主机中的/etc/sysconfig/rsyslog中的参数。
安装配置rsyslog
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

## 此步centos 默认已安装,可以跳过
yum -y install rsyslog

## 修改"SYSLOGD_OPTIONS"参数,
## -c 2 使用兼容模式,默认是 -c 5;
## -r 开启远程日志;
## -m 0 标记时间戳,单位是分钟,0表示禁用该功能。

cp /etc/sysconfig/rsyslog{,.$(date '%F_%T')}

cat > /etc/sysconfig/rsyslog << EOF
SYSLOGD_OPTIONS="-c 2 -r -m 0"

EOF



sed -i "s/#\$ModLoad imudp/\$ModLoad imudp/g" /etc/rsyslog.conf
sed -i "s/#\$UDPServerRun 514/\$UDPServerRun 514/g" /etc/rsyslog.conf

## #文件最末尾的"&~",如果没有此配置,日志除写入指定文件外,会同步写入messages文件;
cat > /etc/rsyslog.d/haproxy.conf << EOF

local2.* /var/log/haproxy.log
&~

EOF

systemctl restart rsyslog.service

配置 Haproxy

##Haproxy 基本配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141


cp /etc/haproxy/haproxy.cfg{,.$(date +'%F_%T')}



cat > /etc/haproxy/haproxy.cfg << EOF

global
#定义全局日志, 配置在本地, 通过local0 输出, 默认是info级别,可配置两条
log 127.0.0.1 local2 warning

chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid

#设置每haproxy进程的最大并发连接数, 其等同于命令行选项“-n”; “ulimit -n”自动计算的结果参照此参数设定.
maxconn 4000
user haproxy
group haproxy

#后台运行haproxy
daemon

## 设置启动的haproxy进程数量, 只能用于守护进程模式的haproxy;
## 默认只启动一个进程
#nbproc 1


#定义统计信息保存位置
#stats socket /var/lib/haproxy/stats
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s


##===============https相关========================================
# Default SSL material locations

ca-base /etc/ssl/certs

crt-base /etc/ssl/private

## Default ciphers to use on SSL-enabled listening sockets.
## 参考:https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
## 需要处理以下事:
## 禁用SSL 2.0(FUBAR)和SSL 3.0 1(POODLE),
## 禁用TLS 1.0压缩(CRIME),
## 禁用弱密码(DES / 3DES,RC4),更喜欢现代密码(AES),模式(GCM)和协议(TLS 1.2)。
## OpenSSL更新为1.0.1c +,以便尽快支持TLS 1.2,GCM和ECDHE
## OpenSSL安装进行测试:
## openssl ciphers -v 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS'


ssl-default-bind-options no-sslv3
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS

ssl-default-server-options no-sslv3
ssl-default-server-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS

tune.ssl.default-dh-param 2048

##============================================================


defaults

#默认的模式【tcp:4层; http:7层; health:只返回OK】
mode http

#日志类别, httplog
log global

#日志类别, httplog
option httplog
#如果产生了一个空连接,那这个空连接的日志将不会记录.
option dontlognull

#开启http协议中服务器端关闭功能, 每个请求完毕后主动关闭http通道, 使得支持长连接,使得会话可以被重用,使得每一个日志记录都会被记录.
option http-server-close

## 需要长连接就注释掉此
# option httpclose

#当haproxy负载很高时, 自动结束掉当前队列处理比较久的链接.
option abortonclose

#如果后端服务器需要记录客户端真实ip, 需要在HTTP请求中添加”X-Forwarded-For”字段;
#但haproxy自身的健康检测机制访问后端服务器时, 不应将记录访问日志,可用except来排除127.0.0.0,即haproxy本身.
option forwardfor except 127.0.0.0/8

#当与后端服务器的会话失败(服务器故障或其他原因)时, 把会话重新分发到其他健康的服务器上; 当故障服务器恢复时, 会话又被定向到已恢复的服务器上;
#还可以用”retries”关键字来设定在判定会话失败时的尝试连接的次数
option redispatch
retries 3


#默认http请求超时时间
timeout http-request 10s

#默认队列超时时间, 后端服务器在高负载时, 会将haproxy发来的请求放进一个队列中.
timeout queue 1m

#haproxy与后端服务器连接超时时间.
timeout connect 10s

#客户端与haproxy连接后, 数据传输完毕, 不再有数据传输, 即非活动连接的超时时间.
timeout client 1m

#haproxy与后端服务器非活动连接的超时时间.
timeout server 1m

#默认新的http请求连接建立的超时时间,时间较短时可以尽快释放出资源,节约资源.
timeout http-keep-alive 10s

#心跳检测超时时间
timeout check 10s


#设置默认的负载均衡方式
#balance source
#balnace leastconn


listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10

## 状态监控可以直接防在default里,任何监听域名或地址都可以访问,也可以单独放在listen里
stats enable
stats hide-version
stats refresh 30s
stats uri /stats
stats realm Haproxy\ Statistics
stats auth test.admin:test.admin!9595
stats refresh 30s
stats admin if TRUE



EOF
## HAProxy作为SSL终端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

## 让负载均衡器处理SSL连接。这就意味着要将SSL证书放在负载均衡服务器上。
## SSL连接终止在负载均衡器haproxy --->解码SSL连接并发送非加密连接到后端应用tomcat.

## 多个不同域名的证书 bind *:443 ssl crt <cert_path> crt <cert_path> ...

cat >> /etc/haproxy/haproxy.cfg << EOF

frontend server_ssl
bind *:80
bind *:443 ssl crt /etc/haproxy/server.pem

## 将http转发至https
redirect scheme https if !{ ssl_fc }

mode http
default_backend server

backend server
mode http
balance roundrobin
option forwardfor
# option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server web01 10.0.0.4:80 maxconn 1024 weight 1 check inter 2000 rise 2 fall 4
server web02 10.0.0.6:80 maxconn 1024 weight 1 check inter 2000 rise 2 fall 4
# http-request set-header X-Forwarded-Port %[dst_port]
# http-request add-header X-Forwarded-Proto https if { ssl_fc }


EOF
## HAProxy实现SSL穿透
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

## 使用SSL穿透,让后台服务器处理SSL连接,而非负载均衡器来处理。
## 负载均衡器的工作就只是简单地将请求转发到配置好的后台服务器。连接还保持加密状态。
## 在这个配置中,需要在前端和后台配置中同时使用TCP模式而不是HTTP模式,HAProxy只会把连接当作信息流来转发到其他服务器.
## 然而,这样做会让你失去增加或修改HTTP报头的能力,这意味着应用服务器会失去获取 X-Forwarded-* 报头的能力,这个报头包含了客户端IP地址、端口和使用的协议。

## 可以使用ssl-hello-chk来检查连接及它处理SSL(特别是SSLv3)连接的能力
## 使用SSL 穿越,不需要给HAProxy创建或使用SSL证书。
## option forwardfor和http-request选项 - 这些不能用于TCP模式,而且我们也不能向已加密的请求添加报头


cat >> /etc/haproxy/haproxy.cfg << EOF

frontend server_ssl
bind *:80
bind *:443
option tcplog
mode tcp
default_backend server

backend server
mode tcp
balance roundrobin
option ssl-hello-chk
server web01 10.0.0.4:80 weight 1 check inter 2000 rise 2 fall 4
server web02 10.0.0.6:80 weight 1 check inter 2000 rise 2 fall 4


EOF

keepalvied 高可用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

cat > /etc/keepalived.conf << EOF

! Configuration File for keepalived

global_defs {
notification_email {
root@sanyu.com
}
notification_email_from kanotify@sanyu.com
smtp_connect_timeout 30
smtp_server 127.0.0.1
router_id LVS_DEVEL
}
vrrp_script chk_haproxy {
script "killall -0 haproxy"
interval 1
weight 2
}
vrrp_script chk_mantaince_down {
script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0"
interval 1
weight 2
}
vrrp_instance VI_1 {
state MASTER # BACKUP for slave routers
interface eth0
virtual_router_id 70
priority 101 # 100 for BACKUP
garp_master_delay 1

authentication {
auth_type PASS
auth_pass password
}
track_interface {
eth0
}
virtual_ipaddress {
172.16.100.70/16 dev eth0 label eth0:0
}
track_script {
chk_haproxy
chk_mantaince_down
}
}
vrrp_instance VI_2 {
interface eth0
state BACKUP # BACKUP for slave routers
priority 100 # 100 for BACKUP
virtual_router_id 79
garp_master_delay 1

authentication {
auth_type PASS
auth_pass password
}
track_interface {
eth0
}
virtual_ipaddress {
172.16.100.79/16 dev eth0 label eth0:1
}
track_script {
chk_haproxy
chk_mantaince_down
}
}


EOF
## 比对两服务器的keepalived配置文件
1
2

diff keepalived.conf keepalived.conf.ha2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

vi /etc/keepalived/check_haproxy.sh

#!/bin/sh

killall -0 haproxy

if [ $? -ne 0 ]; then

## if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
systemctl restart haproxy
## /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg

## fi

sleep 2

killall -0 haproxy

## if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
if [ $? -ne 0 ]; then
killall keepalived
fi

fi

killall -0 haproxy